package cn.lhl01.common.annotation;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * TokenCheck的切面处理器
 */
@Slf4j
@Component
@Aspect
public class TokenCheckAnnotationAspect {
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	@Pointcut("@annotation(cn.lhl01.common.annotation.TokenCheck)")
	private void tokenCheckAnnotationAspect() {
	}

	/**
	 * 环绕通知 在Before之前
	 */
	@Around("tokenCheckAnnotationAspect()")
	public void advice(ProceedingJoinPoint joinPoint) throws Throwable {
		log.debug("around begin...  TokenCheck");
		//被注方法的入参列表
		//Object[] args = joinPoint.getArgs();

		//获取当前注解的参数
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		TokenCheck annotation = method.getAnnotation(TokenCheck.class);
		boolean required = annotation.required();
		String tokenKey = "";
		if (required) {

			//获取当前的请求
			ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = attributes.getRequest();
			tokenKey = request.getHeader(annotation.headerTokenKey());
			if (StrUtil.isBlank(tokenKey)) {
				//Header中没有tokenKey
				throw new AccessDeniedException("TokenCheck失败!");
			}

			if (!redisTemplate.hasKey(tokenKey)) {
				//redis上的key不存在
				throw new AccessDeniedException("TokenCheck失败!");
			}

		}

		//执行到这里走原来的方法
		joinPoint.proceed();

		if (required) {
			//删除这个key 消费掉
			redisTemplate.delete(tokenKey);
		}

		log.debug("around after....TokenCheck");
	}

	/**
	 * 前置
	 * @param joinPoint
	 */
	/*@Before("tokenCheckAnnotationAspect()")
	public void record(JoinPoint joinPoint) {
		System.out.println("Before");
	}*/

	/**
	 * 后置 被注的方法执行完之后
	 */
	/*@After("tokenCheckAnnotationAspect()")
	public void after() {
		System.out.println("After");
	}*/
}


